#encoding:utf8

import sys
import math
import numpy as np

try:
	from OpenGL.GLUT import *
	from OpenGL.GL import *
	from OpenGL.GLU import *
except:
	print '''
ERROR: PyOpenGL not installed properly.  
		'''

s_eye	= [0, 0, 50]
s_at	= [0, 0, 0]
s_angle	= -90
isLeftButtonPressed	= False
xLastMousePos		= 0
yLastMousePos		= 0

class Camera(object):
	def __init__(self):
		self._position	= np.array((0, 0, 0))
		self._up		= np.array((0, 1, 0))
		self.radYaw		= math.pi * 0.5 
		self.radPitch	= -math.pi * 0.5
		self._resetDirection()
	
	@property
	def position(self):
		return self._position

	@position.setter
	def position(self, value):
		self._position	= value

	@property
	def right(self):
		return np.cross(self._direction, self._up)

	@property
	def direction(self):
		return self._direction

	def _resetDirection(self):
		sin, cos		= math.sin, math.cos
		self._direction	= np.array((cos(self.radPitch) * sin(self.radYaw), cos(self.radYaw), sin(self.radPitch) * sin(self.radYaw)))
	
	def yaw(self, rad):
		self.radYaw		+= rad
		self._resetDirection()

	def pitch(self, rad):
		self.radPitch	+= rad
		self._resetDirection()

	def lookAt(self):
		glLoadIdentity()
		center	= self._position + self._direction
		gluLookAt(self._position[0], self._position[1], self._position[2], center[0], center[1], center[2], 0, 1, 0)


camera	= Camera()
camera.position	= np.array((0, 0, 40))

def init(): 
	glClearColor (0.0, 0.0, 0.0, 0.0)
	glClearDepth(1.0)
	glShadeModel (GL_SMOOTH)
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)

def display():
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

	glColor3f (1.0, 1.0, 1.0)
	global camera
	camera.lookAt()

	# viewing transformation 

	glScalef (1.0, 2.0, 1.0)		 # modeling transformation 
	glutWireCube (1.0)

	glBegin(GL_LINES)
	xMax	= 10
	yMax	= 10
	for x in xrange(-xMax, xMax + 1):
		glVertex3f(x, -yMax, 0)
		glVertex3f(x, yMax, 0)

	for y in xrange(-yMax, yMax + 1):
		glVertex3f(-xMax, y, 0)
		glVertex3f(xMax, y, 0)

	glEnd()


	glutSwapBuffers()

def reshape (width, height):
	width	= width or 1
	height	= height or 1
	glViewport (0, 0, width, height)

	glMatrixMode (GL_PROJECTION)
	glLoadIdentity ()
	# glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0)
	gluPerspective(60, width/height, 1.0, 100)
	glMatrixMode (GL_MODELVIEW)

def keyboard(key, x, y):
	escape	= chr(27)
	if key == escape:
		sys.exit(0)
	
	key	= key.upper()
	global camera

	speed	= 1.0

	if key == 'A':
		camera.position	= camera.position - camera.right * speed
	elif key == 'D':
		camera.position	= camera.position + camera.right * speed

	
	if key == 'W':
		camera.position	= camera.position + camera.direction * speed
	elif key == 'S':
		camera.position	= camera.position - camera.direction * speed

def mouse(button, state, x, y):
	if button ==GLUT_LEFT_BUTTON:
		global isLeftButtonPressed
		if state == GLUT_DOWN:
			isLeftButtonPressed	= True
			xLastMousePos		= x
			yLastMousePos		= y
		else:
			isLeftButtonPressed	= False

def motion(x, y):
	global isLeftButtonPressed
	if isLeftButtonPressed:
		global xLastMousePos, yLastMousePos
		xDelta	= x - xLastMousePos
		yDelta	= y	- yLastMousePos
		xLastMousePos	= x
		yLastMousePos	= y
		global camera

		scale	= math.pi / 180  * 0.1
		camera.yaw(yDelta * scale)
		camera.pitch(xDelta* scale)

		# print(xDelta, yDelta)

def main():
	glutInit(sys.argv)
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB)
	glutInitWindowSize (500, 500)
	glutInitWindowPosition (100, 100)
	glutCreateWindow ('cube')
	init ()
	glutDisplayFunc(display)
	glutIdleFunc(display)
	glutReshapeFunc(reshape)
	glutKeyboardFunc(keyboard)
	glutMouseFunc(mouse)
	glutMotionFunc(motion)
	glutMainLoop()

if __name__=='__main__':
	main()
